
import javax.imageio.ImageIO;
import javax.swing.*;
import java.awt.*;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.image.BufferedImage;
import java.io.*;

import Audio.Audio;
import Controller.Engine;

/**
 * Created by akasiyanenko@stud.fh-luebeck.de on 12.10.2014.
 */
public class GamePanel extends JPanel implements Runnable, KeyListener {

    public static final int WIDTH = 480;
    public static final int HEIGHT = 320;
    public static final int SCALE = 2;
    public static final int CELL_SIZE = 16;

    private Thread thread;
    private boolean running;

    private Image background;
    private Graphics2D g;

    private int FPS = 30;
    private int targetTime = 1000 / FPS;

    Thread audio = new Audio("resources/audio/puss-3step.wav", 182000);
    final public static boolean MUSIC_ENABLED = true;

    private String Name = "";
    private int AnzahlLebenPlayer = 3;
    private boolean bPlayMusic = true;
    private int Level = 1;
    private int Score = 0;

    private Engine game;

    public GamePanel(int iAnzLeben, boolean bPlayMusic, int iStartLevel, String name) {

        super();

        Name = name;
        this.bPlayMusic = bPlayMusic;
        if (iAnzLeben > 0) {
            AnzahlLebenPlayer = iAnzLeben;
        }
        if (iStartLevel > 0) {
            Level = iStartLevel;
        }

        setPreferredSize(new Dimension(WIDTH * SCALE, HEIGHT * SCALE));
        setFocusable(true);
        setBackground(Color.DARK_GRAY);
        requestFocus();
    }

    public void addNotify() {
        super.addNotify();

        if(thread == null) {
            thread = new Thread(this);
            addKeyListener(this);
            thread.start();
        }
    }

    public void threadEnded(){
        System.out.println("Leben weg");
        // "Collision"?:
        if (game.has_collision() ){
            //Reset:
            game.unset_collision();
            AnzahlLebenPlayer--;

            final JPanel panel = new JPanel();
            if (AnzahlLebenPlayer == 0)
            {
                HighScore highScore = new HighScore();
                highScore.setLocalScores(Score);
                highScore.setOnlineScores(Name, Score);

                JOptionPane.showMessageDialog(panel, "Spiel beendet!", "Schade",
                        JOptionPane.WARNING_MESSAGE);
                System.exit(0);
            }
            else
            {
                String strLives = Integer.toString(AnzahlLebenPlayer);
                JOptionPane.showMessageDialog(panel, "Noch " + strLives + " Leben uebrig.", "Kollision!",
                        JOptionPane.WARNING_MESSAGE);
            }
        }
        else if (game.is_dest_reached()){
            // Reset "Destination reached"-State:
            game.unset_dest_reached();
            final JPanel panel = new JPanel();
            JOptionPane.showMessageDialog(panel, "Sehr gut!", "Geschafft!",
                    JOptionPane.WARNING_MESSAGE);

            Level++;
        }

        // Restart
        //removeKeyListener(this);
        thread = new Thread(this);
        //addKeyListener(this);
        thread.start();



    }

    public void run() {
        init();

        // Hintergrundmusik laufen lassen
        if (bPlayMusic){
            audio.start();

            // Thread darf nur ein mal gestartet werden
            bPlayMusic = false;
        }

        long deltaTime = 01;

        // Buffering damit das Flimmern verhindert wird
        BufferedImage screen = new BufferedImage(WIDTH * SCALE, HEIGHT * SCALE, BufferedImage.TYPE_INT_RGB);
        Graphics g = screen.getGraphics();
        Graphics appletGraphics = getGraphics();

        while(running){
            long startTime = System.nanoTime();

            // hintergrundsbild zeichnen
            g.drawImage(background, 0, 0, WIDTH * SCALE, HEIGHT * SCALE, null);

            // Spiele Engine aktualisieren
            game.update((float)(deltaTime / 1000000000.0), Level);
            game.render(g, Level, Score);
            running = !( (game.has_collision() || game.is_dest_reached() ) );
            // alles zeichnen
            appletGraphics.drawImage(screen, 0, 0, null);

            // Berechnen, wie lange muss das Programm warten, damit die Anzahl der Frames nicht
            // ueberschritten wird
            deltaTime = System.nanoTime() - startTime;
            if (deltaTime < 20000000L) {
                // Anzahl der Frames begrenzen, indem der Thread pausiert wird
                try {
                    //System.out.println("sleeping for " + waitTime + " delta= "+ (float)(deltaTime / 1000000000.0));
                    Thread.sleep((20000000L - deltaTime) / 1000000L);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }// if
        }// while
        threadEnded();
    }// run()

    public void init() {
        running = true;

       game = new Engine(WIDTH, HEIGHT, SCALE, CELL_SIZE, AnzahlLebenPlayer);

        if(background == null) {
            background = getBackground("resources/image/tilemap_grid.png");
        }
    }// init()

    /**
     * Load Background from File
     * @param path Der Pfad zum Hintergrund Bild
     * @return Image
     */
    private Image getBackground(String path) {

        Image tempImage = null;

        try {
            tempImage = ImageIO.read(new File(path));
        } catch (IOException e) {
            System.out.println("image not found");
        }

        return tempImage;
    }

    public void keyTyped(KeyEvent key) {}

    /**
     * Auswertung der Eingaben des Spielers
     * @param key Die gedrückte Taste
     */
    public void keyPressed(KeyEvent key) {
        boolean playerMoved = game.keyPressed(key.getKeyCode());

        if (playerMoved) {
            if (key.getKeyCode() == KeyEvent.VK_UP) {
                Score += Level;
            }
            else if (key.getKeyCode() == KeyEvent.VK_DOWN) {
                Score -= Level;
            }
        }
    }

    public void keyReleased(KeyEvent key) {
        game.keyReleased(key.getKeyCode());
    }
}
